import * as vscode from "vscode";
/**
 * 实现VSCode文档颜色提供者的类【RGBAColor】
 * 该类用于在文档中提供和呈现颜色信息
 */
export class RGBAColorProvider implements vscode.DocumentColorProvider {
  /**
   * 提供文档中的颜色信息
   * 该方法遍历文档的每一行，查找符合特定正则表达式的游戏颜色对象，并将其转换为VSCode的颜色信息对象
   *
   * @param document vscode.TextDocument - 要分析的颜色的文本文档
   * @returns vscode.ProviderResult<vscode.ColorInformation[]> - 一个表示文档中颜色信息的数组
   */
  public provideDocumentColors(
    document: vscode.TextDocument,
  ): vscode.ProviderResult<vscode.ColorInformation[]> {
    const colorInfos: vscode.ColorInformation[] = []; // 存储颜色信息的数组
    document
      .getText()
      .split("\n")
      .forEach((line, index) => {
        // 遍历文档的每一行
        const colorRegex = /new\s+(?:GameRGBColor|GameRGBAColor)\(([^)]*)\)/g; // 匹配游戏颜色对象的正则表达式
        let match;
        while ((match = colorRegex.exec(line)) !== null) {
          // 在当前行中查找所有匹配的颜色对象
          let arg = match[1].split(","); // 将匹配到的颜色对象的参数分割成数组
          const red = Number(arg[0] ?? 0);
          const green = Number(arg[1] ?? 0);
          const blue = Number(arg[2] ?? 0);
          const alpha = arg.length === 4 ? Number(arg[3]) : 1; // 如果有4个参数，则第4个参数为alpha，否则默认为1
          const color = new vscode.Color(red, green, blue, alpha); // 创建VSCode颜色对象
          const range = new vscode.Range(
            index,
            match.index,
            index,
            match.index + match[0].length,
          ); // 创建颜色对象的范围
          colorInfos.push(new vscode.ColorInformation(range, color)); // 将颜色信息添加到数组中
        }
      });

    return colorInfos;
  }

  /**
   * 提供颜色的呈现方式
   * 该方法接收一个VSCode颜色对象，将其转换为游戏颜色对象的字符串，并返回一个颜色呈现对象的数组
   *
   * @param color vscode.Color - 要呈现的颜色
   * @returns vscode.ProviderResult<vscode.ColorPresentation[]> - 一个表示颜色呈现方式的数组
   */
  public provideColorPresentations(
    color: vscode.Color,
    context: {
      readonly document: vscode.TextDocument;
      readonly range: vscode.Range;
    },
  ): vscode.ProviderResult<vscode.ColorPresentation[]> {
    let red = color.red.toFixed(2);
    let green = color.green.toFixed(2);
    let blue = color.blue.toFixed(2);
    let alpha = color.alpha.toFixed(2);
    let label;
    if (context.document.getText(context.range).includes("GameRGBAColor")) {
      label = `new GameRGBAColor(${red},${green},${blue},${alpha})`;
    } else {
      label = `new GameRGBColor(${red},${green},${blue})`;
    }
    return [
      {
        label,
      },
    ];
  }
}

/**
 * 实现VSCode文档颜色提供者的类【Vec3】
 * 该类用于在文档中提供和呈现颜色信息
 */
export class Vec3ColorProvider implements vscode.DocumentColorProvider {
  /**
   * 提供文档中的颜色信息
   * 该方法遍历文档的每一行，查找符合特定正则表达式的游戏颜色对象，并将其转换为VSCode的颜色信息对象
   *
   * @param document vscode.TextDocument - 要分析的颜色的文本文档
   * @returns vscode.ProviderResult<vscode.ColorInformation[]> - 一个表示文档中颜色信息的数组
   */
  public provideDocumentColors(
    document: vscode.TextDocument,
  ): vscode.ProviderResult<vscode.ColorInformation[]> {
    const colorInfos: vscode.ColorInformation[] = []; // 存储颜色信息的数组
    document
      .getText()
      .split("\n")
      .forEach((line, index) => {
        // 遍历文档的每一行
        const colorRegex = /Vec3.create\(([^)]+)\)/g; // 匹配游戏颜色对象的正则表达式
        let match;
        while ((match = colorRegex.exec(line)) !== null) {
          // 在当前行中查找所有匹配的颜色对象
          const rMatch = match[0].match(/r:\s*(\d+)/);
          const gMatch = match[0].match(/g:\s*(\d+)/);
          const bMatch = match[0].match(/b:\s*(\d+)/);

          if (!rMatch || !gMatch || !bMatch) {
            // 忽略无效的颜色值
            continue;
          }
          const red = rMatch ? parseInt(rMatch[1], 10) / 255 : 0;
          const green = gMatch ? parseInt(gMatch[1], 10) / 255 : 0;
          const blue = bMatch ? parseInt(bMatch[1], 10) / 255 : 0;
          const alpha = 1;
          const color = new vscode.Color(red, green, blue, alpha); // 创建VSCode颜色对象
          const range = new vscode.Range(
            index,
            match.index,
            index,
            match.index + match[0].length,
          ); // 创建颜色对象的范围
          colorInfos.push(new vscode.ColorInformation(range, color)); // 将颜色信息添加到数组中
        }
      });

    return colorInfos;
  }

  /**
   * 提供颜色的呈现方式
   * 该方法接收一个VSCode颜色对象，将其转换为游戏颜色对象的字符串，并返回一个颜色呈现对象的数组
   *
   * @param color vscode.Color - 要呈现的颜色
   * @returns vscode.ProviderResult<vscode.ColorPresentation[]> - 一个表示颜色呈现方式的数组
   */
  public provideColorPresentations(
    color: vscode.Color,
  ): vscode.ProviderResult<vscode.ColorPresentation[]> {
    let red = Math.round(color.red * 255);
    let green = Math.round(color.green * 255);
    let blue = Math.round(color.blue * 255);
    let label = `Vec3.create({r:${red},g:${green},b:${blue}})`;
    return [
      {
        label,
      },
    ];
  }
}

/**
 * 实现VSCode文档颜色提供者的类【XMLColor】
 * 该类用于在文档中提供和呈现颜色信息
 */
export class XMLColorColorProvider implements vscode.DocumentColorProvider {
  /**
   * 提供文档中的颜色信息
   * 该方法遍历文档的每一行，查找符合特定正则表达式的游戏颜色对象，并将其转换为VSCode的颜色信息对象
   *
   * @param document vscode.TextDocument - 要分析的颜色的文本文档
   * @returns vscode.ProviderResult<vscode.ColorInformation[]> - 一个表示文档中颜色信息的数组
   */
  public provideDocumentColors(
    document: vscode.TextDocument,
  ): vscode.ProviderResult<vscode.ColorInformation[]> {
    const colorInfos: vscode.ColorInformation[] = []; // 存储颜色信息的数组
    document
      .getText()
      .split("\n")
      .forEach((line, index) => {
        // 遍历文档的每一行
        const colorRegex = /color="(#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})|)"/g; // 匹配游戏颜色对象的正则表达式
        let match;
        while ((match = colorRegex.exec(line)) !== null) {
          // 在当前行中查找所有匹配的颜色对象
          const color = new vscode.Color(
            parseInt(match[1].slice(1, 3) ?? "00", 16) / 255,
            parseInt(match[1].slice(3, 5) ?? "00", 16) / 255,
            parseInt(match[1].slice(5, 7) ?? "00", 16) / 255,
            1,
          );
          const range = new vscode.Range(
            index,
            match.index,
            index,
            match.index + match[0].length,
          ); // 创建颜色对象的范围
          colorInfos.push(new vscode.ColorInformation(range, color)); // 将颜色信息添加到数组中
        }
      });

    return colorInfos;
  }

  /**
   * 提供颜色的呈现方式
   * 该方法接收一个VSCode颜色对象，将其转换为游戏颜色对象的字符串，并返回一个颜色呈现对象的数组
   *
   * @param color vscode.Color - 要呈现的颜色
   * @returns vscode.ProviderResult<vscode.ColorPresentation[]> - 一个表示颜色呈现方式的数组
   */
  public provideColorPresentations(
    color: vscode.Color,
  ): vscode.ProviderResult<vscode.ColorPresentation[]> {
    const red = Math.round(color.red * 255)
      .toString(16)
      .padStart(2, "0");
    const green = Math.round(color.green * 255)
      .toString(16)
      .padStart(2, "0");
    const blue = Math.round(color.blue * 255)
      .toString(16)
      .padStart(2, "0");
    // const alpha = Math.round(color.alpha * 255).toString(16).padStart(2, '0');

    // 返回带有透明度的十六进制颜色字符串
    const label = `color="#${red}${green}${blue}"`;
    return [
      {
        label,
      },
    ];
  }
}
